package cn.com.aiouyi.util;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;

/**
 * 公共工具类
 * @author:hanson
 */
public class CommUtil {

	public static final String DATE_FORMAT_yyyy_MM_dd_HH_mm_ss = "yyyyMMdd_HHmmss";
	public static final String DATE_FORMAT_yyyy_MM_ddHH_mm_ss = "yyyyMMddHHmmss";
	public static final String DATE_FORMAT_yyyy_MM_dd = "yyyyMMdd";

	private static final Logger log = LoggerFactory.getLogger(CommUtil.class);
	
	private static CommUtil instance = new CommUtil();
	/**默认格式化日期*/
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
	
	private CommUtil(){}
	
	/**
	 * 单例模式
	 * @return
	 */
	public static CommUtil getInstance(){
		return instance;
	}
	
	/**
    * 判断对象是否为null或者空字符串
    * @author:hanson
    */
	public static boolean isNotNull(Object obj)
	{
	   return (obj != null) && (!obj.toString().equals(""));
	}
	
	public static boolean isNull(Object obj)
	{
	   return (obj == null) || (obj.toString().equals(""));
	}
	
	/**
	 * 转整型
	 * @param obj
	 * @author:hanson
	 */
	public static int null2Int(Object obj){
		int value = 0;
		try{
			value = Integer.parseInt(obj.toString());
		}catch(Exception e){
			log.info("整型转换错误");
		}
	    return value;
	}
	
	/**
	 * 
	 * @Description: 将obj转为Float,默认为0.0f
	 * @param s
	 * @return
	 */
	public static float null2Float(Object s) {
		float v = 0.0F;
		if (s != null)
			try {
				v = Float.parseFloat(s.toString());
			} catch (Exception localException) {
			}
		return v;
	}

	/**
	 * 
	 * @Description: 将obj转为double,默认为0.0d
	 * @param s
	 * @return
	 */
	public static double null2Double(Object s) {
		double v = 0.0D;
		if (s != null)
			try {
				v = Double.parseDouble(null2String(s));
			} catch (Exception localException) {
			}
		return v;
	}

	/**
	 * 
	 * @Description: 将obj转为boolean,默认为false
	 * @param s
	 * @return
	 */
	public static boolean null2Boolean(Object s) {
		boolean v = false;
		if (s != null)
			try {
				v = Boolean.parseBoolean(s.toString());
			} catch (Exception localException) {
			}
		return v;
	}

	/**
	 * 
	 * @Description: 将obj转为String,默认为""
	 * @param s
	 * @return
	 */
	public static String null2String(Object s) {
		return s == null ? "" : s.toString().trim();
	}
	
	/**
	 * 
	 * @Description: 将obj转为Long,默认为new Long(-1L);
	 * @param s
	 * @return
	 */
	public static Long null2Long(Object s) {
		Long v = Long.valueOf(-1L);
		if (s != null)
			try {
				v = Long.valueOf(Long.parseLong(s.toString()));
			} catch (Exception localException) {
			}
		return v;
	}
	
	/**
	 * 判断字符串数组中是否包含有某个字符串
	 * @param item
	 * @param array
	 * @return
	 */
	public static boolean isContainStr(String[] array ,String item){
		if(isNull(item) || isNull(array)){
			return false;
		}else{
			for(String str : array){
				if(str.equals(item)){
					return true; 
				}
			}
		}
		return false;
	}
	
	/**
	 * 获取字符串中某个字符出现的个数
	 * @param str
	 * @param c
	 * @return
	 */
	public static int getCharCountInStr(String str, char c){
		int count = 0;
		for(char ch : str.toCharArray()){
			if(ch == c) count++;
		}
		return count;
	}

	/**
	 * 判断当前字符串是否都是数字
	 * */
	public static boolean isInteger(String str) {
		Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
		return pattern.matcher(str).matches();
	}

	/**
	 * 根据日期字符串  转化为Date日期格式    yyyy-MM-dd
	 * @param dateStr
	 * @return 
	 */
	public static Date formatShortDateStr(String dateStr){
		dateStr = correctTimeStr(dateStr);
		Date date = null;
		try {
			date = dateFormat.parse(dateStr);
		} catch (ParseException e) {
			log.info("日期解析错误");
		}
		return date;
	}
	/**
	 * 根据日期字符串  转化为Date日期格式    yyyy-MM-dd HH:mm:ss
	 * @param dateStr
	 * @return
	 */
	public static Date formatLongDateStr(String dateStr){
		dateStr = correctTimeStr(dateStr);
		Date date = null;
		try {
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			date = df.parse(dateStr);
		} catch (ParseException e) {
			log.info("日期解析错误");
		}
		return date;
	}
	/**
	 * 纠正不标准的日期格式
	 * @param timeStr
	 * @return
	 */
	private static String correctTimeStr(String timeStr){
		if(timeStr == null) return null;
		timeStr = timeStr.trim().replaceAll("\\s{1,}", " "); // 去除多余的空格
		timeStr = timeStr.replaceAll("[./。、]", "-").replaceAll("：", ":"); // 转成标准格式 
		return timeStr;
	}
	/**
	 * 格式化日期为指定格式的字符串，"yyyy-MM-dd HH:mm:ss"
	 * @return 
	 */
	public static String formatLongDate(Object v) {
		if ((v == null) || (v.equals("")))
			return "";
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return df.format(v);
	}

	/**
	 * 格式化日期为指定格式的字符串
	 * @return
	 */
	public static String formatDate(Object v, String format) {
		if ((v == null) || (v.equals("")))
			return "";
		SimpleDateFormat df = new SimpleDateFormat(format);
		return df.format(v);
	}

	/**
	 * 格式化日期为指定格式的字符串，"yyyy-MM-dd"
	 * @return
	 */
	public static String formatShortDate(Object v) {
		if (v == null) return null;
		return dateFormat.format(v);
	}

	/** 
     * 下划线转驼峰 
     * @param str 
     * @return 
     */  
    public static String underlineToCamel(String str) {  
        //利用正则删除下划线，把下划线后一位改成大写  
        Pattern pattern = Pattern.compile("_(\\w)");  
        Matcher matcher = pattern.matcher(str);  
        StringBuffer sb = new StringBuffer(str);  
        if(matcher.find()) {  
            sb = new StringBuffer();  
            //将当前匹配子串替换为指定字符串，并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象里。  
            //正则之前的字符和被替换的字符  
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());  
            //把之后的也添加到StringBuffer对象里  
            matcher.appendTail(sb);           
        }else {  
            return sb.toString();  
        }     
        return underlineToCamel(sb.toString());  
    }  
      
      
    /** 
     * 驼峰转下划线 
     * @param str 
     * @return 
     */  
    public static String camelToUnderline(String str) {  
        Pattern pattern = Pattern.compile("[A-Z]");  
        Matcher matcher = pattern.matcher(str);  
        StringBuffer sb = new StringBuffer(str);  
        if(matcher.find()) {  
            sb = new StringBuffer();  
            //将当前匹配子串替换为指定字符串，并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象里。  
            //正则之前的字符和被替换的字符  
            matcher.appendReplacement(sb,"_"+matcher.group(0).toLowerCase());  
            //把之后的也添加到StringBuffer对象里  
            matcher.appendTail(sb);           
        }else {  
            return sb.toString();  
        }     
        return camelToUnderline(sb.toString());  
    }
	
	/**
	 * 获取请求的上下文路径
	 * @author hanson
	 * @param request
     * @return 上下文路径（/+项目名）
	 */
	public static String getContextPath(HttpServletRequest request){
		String contextPath = request.getContextPath().equals("/") ? "" : request.getContextPath();
		return contextPath;
	}
	
	/**
     * 获取请求的绝对路径（URL去掉资源路径）
     * @author hanson
     * @param request
     * @return 请求的绝对路径（协议+服务器名+端口+项目名）
     */
	public static String getWebPath(HttpServletRequest request) {
		String url = "http://" + request.getServerName();
			if (null2Int(Integer.valueOf(request.getServerPort())) != 80)
				url = url + ":" + null2Int(Integer.valueOf(request.getServerPort())) + getContextPath(request);
			else {
				url = url + getContextPath(request);
			}
		return url;
	}
	
	/**
     * 获得工程的classpath根目录
     * @author hanson
     * @return String
     */
	public static String getClasspath() {
	    try {
	    	// 随便填一个class类
	        return Class.forName("net.shop.entity.BaseEntity").getResource("/").getPath();
	    } catch (Exception e) {
	    	log.info("获取classpath错误", e);
	    }
	    return "";
	}
	 
	/**
	 * 获得工程的WebRoot根目录
	 * @author hanson
	 * @return String
	 */
	public static String getWebRootPath() {
	    try {
	        String classpath = getClasspath();// classes 目录的物理路径
	        String webInfoPath = new File(classpath).getParent();// WEB-INF 目录的物理路径
	        return new File(webInfoPath).getParent();// WebRoot 目录的物理路径
	    } catch (Exception e) {
	    	log.info("获取WebRoot根目录错误", e);
	    }
	    return "";
	}
	
	/**
	 * 获取项目部署的真实目录 跟getWebRootPath()差不多，但是通过request获取更准确
	 * @param request
	 * @return
	 */
	public static String getRealPath(HttpServletRequest request){
		String real_path = request.getSession().getServletContext().getRealPath("/");
		return real_path;
	}
	
	public static String getRealPath(ServletContext servletContext){
		String real_path = servletContext.getRealPath("/");
		return real_path;
	}
	
	/**
	* @Description: 获取客户端真实IP地址（解决了使用反向代理软件获取不到IP的情况）
	* @param request
	* @return
	*/
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
	    if ((ip == null) || (ip.length() == 0) || ("unknown".equalsIgnoreCase(ip))) {
	    	ip = request.getHeader("Proxy-Client-IP");
	    }
	    if ((ip == null) || (ip.length() == 0) || ("unknown".equalsIgnoreCase(ip))) {
	    	ip = request.getHeader("WL-Proxy-Client-IP");
	    }
	    if ((ip == null) || (ip.length() == 0) || ("unknown".equalsIgnoreCase(ip))) {
	    	ip = request.getRemoteAddr();//返回客户端的ip地址
	    }
	    return ip;
    }

    public static ServletContext getServletContextBySpring(){
    	WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();    
        ServletContext servletContext = webApplicationContext.getServletContext();
        return servletContext;
    }
    
    public static class Array {
    	
    	/**
    	 * 多个数组取交集
    	 * @param array
    	 * @return
    	 */
    	public static String[] intersect(String[]... arrays){
    		List<String> result = new ArrayList<String>();
    		Map<String, Integer> map = new HashMap<String, Integer>();
    		for(String[] array : arrays){
    			for(String str : array){
    				if(map.get(str)==null){
    					map.put(str, 1);
    				}else{
    					map.put(str, map.get(str)+1);
    					if(map.get(str) == arrays.length){
    						result.add(str);
    					}
    				}
    			}
    		}
    		return result.toArray(new String[]{});
    	}
    	
    	/**
    	 * 两个数组取差集  arr1 - arr2
    	 * @param arr1
    	 * @param arr2
    	 * @return
    	 */
    	public static String[] minus(String[] arr1, String[] arr2){
    		List<String> result = new ArrayList<String>();
    		Map<String, Integer> map = new HashMap<String, Integer>();
    		for(String str2 : arr2){
    			map.put(str2, 1);
    		}
    		for(String str1 : arr1){
    			if(map.get(str1) == null){
    				map.put(str1, 1);
    				result.add(str1);
    			}
    		}
    		return result.toArray(new String[]{});
    	}
    }

	/**
	 * 将map中的key-value保存到一个JSONObject中
	 * @param map 参数map
	 * */
	public static JSONObject mapToJsonObject(Map map){
		JSONObject jo = new JSONObject();
		Iterator it = map.keySet().iterator();
		while (it.hasNext()){
			String key = it.next().toString();
			Object value = map.get(key);
			jo.put(key, value);
		}
		return jo;
	}
}
